/*

    This file is part of GLua

    GLua Development Environment
    Copyright (C) 2007 VoiDeD

    GLua is free software; you can redistribute it and/or modify
    it under the terms of the GNU Lesser General Public License as published by
    the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.

    GLua is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU Lesser General Public License for more details.

    You should have received a copy of the GNU Lesser General Public License
    along with this program.  If not, see <http://www.gnu.org/licenses/>.

*/
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;
using System.IO;
using TD;
using TD.SandDock;
using QWhale;
using QWhale.Common;
using QWhale.Design;
using QWhale.Design.Dialogs;
using QWhale.Editor;
using QWhale.Editor.Dialogs;
using QWhale.Syntax;
using System.Diagnostics;
using System.Xml.Serialization;

namespace GLua
{
    public partial class MainForm : Form
    {
        //
        // if you haven't read the introduction in Program.cs, I'd recommend you do that now
        //

        EnvironmentManager environment;
        string fMsg = "";

        public MainForm()
        {
            InitializeComponent();


            this.imageList1.Images.Add( "root", global::GLua.Properties.Resources.project_root );
            this.imageList1.Images.Add( "code", global::GLua.Properties.Resources.project_code );
            this.imageList1.Images.Add( "tasklist_checkbox", global::GLua.Properties.Resources.tasklist_checkbox );
            this.imageList1.Images.Add( "server", global::GLua.Properties.Resources.function_server );
            this.imageList1.Images.Add( "client", global::GLua.Properties.Resources.function_client );
            this.imageList1.Images.Add( "shared", global::GLua.Properties.Resources.function_shared );
            this.imageList1.Images.Add( "library", global::GLua.Properties.Resources.library );
            this.imageList1.Images.Add( "keyword", global::GLua.Properties.Resources.keyword );
            this.imageList1.Images.Add( "folder_open", global::GLua.Properties.Resources.project_folder_open );
            this.imageList1.Images.Add( "folder_closed", global::GLua.Properties.Resources.project_folder_closed );
            this.imageList1.Images.Add( "file_lost", global::GLua.Properties.Resources.file_unavailable );

            environment = new EnvironmentManager( sandDockManager1, treeView1, imageList1, contextMenuStrip1, contextMenuStrip2, contextMenuStrip3, contextMenuStrip4, contextMenuStrip6, projectExplorer, taskList, outputWindow );

            ( ( Bitmap )this.taskList.TabImage ).MakeTransparent( Color.Magenta );
            ( ( Bitmap )this.outputWindow.TabImage ).MakeTransparent( Color.Magenta );
            ( ( Bitmap )this.projectExplorer.TabImage ).MakeTransparent( Color.Magenta );


            toolStripComboBox1.SelectedIndex = 0;


        }
        public MainForm( string proj )
            : this()
        {
            FileInfo fi = null;
            try
            {
                fi = new FileInfo( proj );
            }
            catch
            {
                return;
            }
            if ( !fi.Exists )
                return;

            if ( fi.Extension == ".glu" )
            {
                Project project = Project.LoadProject( proj );
                if ( project == null )
                    return;

                project.FullName = proj;
                project.Path = new FileInfo( proj ).Directory.FullName;
                project.Saved = true;
                environment.AddProject( project );
            }
            else if ( fi.Extension == ".lua" )
            {
                OpenedFile of = new OpenedFile();
                of.FullName = proj;
                of.Name = fi.Name;
                of.Saved = true;

                environment.ShowOpenedFile( of );
            }
        }

        // file menu actions
        private void newProjectToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.NewProject();
        }
        private void openProjectToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.OpenProject();
        }
        private void openToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.OpenFile();
        }
        private void closeProjectToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.CloseProject();
        }
        private void saveProjectToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.SaveProject();
        }
        private void exitToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( environment.Exit() )
                this.Close();
        }
        private void closeToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.CloseActiveTab();
        }
        private void saveToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.SaveActiveTab();
        }

        // edit menu actions
        private void undoToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( environment.CanUndo() )
                environment.Undo();
        }
        private void redoToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( environment.CanRedo() )
                environment.Redo();
        }
        private void cutToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( environment.CanCut() )
                environment.Cut();
        }
        private void copyToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( environment.CanCopy() )
                environment.Copy();
        }
        private void pasteToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( environment.CanPaste() )
                environment.Paste();
        }
        private void deleteToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( environment.CanDelete() )
                environment.Delete();
        }
        private void selectAllToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( environment.IsTabOpen() )
                environment.SelectAll();
        }
        private void findToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.FindDialog();
        }
        private void replaceToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.ReplaceDialog();
        }

        // view menu actions
        private void projectExplorerToolStripMenuItem_Click( object sender, EventArgs e )
        {
            projectExplorer.Open();
        }
        private void objectBrowserToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.ShowObjectBrowser();
        }
        private void taskListToolStripMenuItem_Click( object sender, EventArgs e )
        {
            taskList.Open();
        }
        private void outputToolStripMenuItem_Click( object sender, EventArgs e )
        {
            outputWindow.Open();
        }

        // project menu actions
        private void addNewItemToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.AddNewItem();
        }
        private void addExistingItemToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.AddExistingItem();
        }
        private void generateInfoFileToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.GenerateInfoFile();
        }
        private void projectPropertiesToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.ShowProjectInfo();
        }

        // tool menu actions
        private void optionsToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.ShowSettingsDialog();
        }

        // help menu actions
        private void garrysModLuaWikiToolStripMenuItem_Click( object sender, EventArgs e )
        {
            try
            {
                Process.Start( "http://garrysmod.com/wiki/" );
            }
            catch { }
        }
        private void facepunchLuaScriptingToolStripMenuItem_Click( object sender, EventArgs e )
        {
            try
            {
                Process.Start( "http://forums.facepunchstudios.com/forumdisplay.php?f=65" );
            }
            catch { }
        }
        private void gLuaHomepageToolStripMenuItem_Click( object sender, EventArgs e )
        {
            try
            {
                Process.Start( "http://glua.net/" );
            }
            catch { }
        }
        private void aboutToolStripMenuItem_Click( object sender, EventArgs e )
        {
            new AboutDialog().ShowDialog( this );
        }
        private void reportABugToolStripMenuItem_Click( object sender, EventArgs e )
        {
            try
            {
                Process.Start( StringTable.BugReportURL );
            }
            catch { }
        }

        // quick strip actions
        private void toolStripButton2_Click( object sender, EventArgs e )
        {
            // new project
            environment.NewProject();
        }
        private void toolStripSplitButton1_ButtonClick( object sender, EventArgs e )
        {
            // new item
            environment.AddNewItem();
        }
        private void addNewItemToolStripMenuItem1_Click( object sender, EventArgs e )
        {
            environment.AddNewItem();
        }
        private void addExistingItemToolStripMenuItem1_Click( object sender, EventArgs e )
        {
            environment.AddExistingItem();
        }
        private void toolStripButton4_Click( object sender, EventArgs e )
        {
            // open file
            environment.OpenFile();
        }
        private void toolStripButton5_Click( object sender, EventArgs e )
        {
            // save active
            if ( environment.IsTabOpen() )
                environment.SaveActiveTab();
        }
        private void toolStripButton6_Click( object sender, EventArgs e )
        {
            // save project
            if ( environment.IsProjectOpen() )
                environment.SaveProject();
        }
        private void toolStripButton7_Click( object sender, EventArgs e )
        {
            // cut
            if ( environment.CanCut() )
                environment.Cut();
        }
        private void toolStripButton8_Click( object sender, EventArgs e )
        {
            // copy
            if ( environment.CanCopy() )
                environment.Copy();
        }
        private void toolStripButton9_Click( object sender, EventArgs e )
        {
            // paste
            if ( environment.CanPaste() )
                environment.Paste();
        }
        private void toolStripButton10_Click( object sender, EventArgs e )
        {
            // undo
            if ( environment.CanUndo() )
                environment.Undo();
        }
        private void toolStripButton11_Click( object sender, EventArgs e )
        {
            // redo
            if ( environment.CanRedo() )
                environment.Redo();
        }
        private void toolStripButton20_Click( object sender, EventArgs e )
        {
            environment.FindDialog();
        }
        private void toolStripButton21_Click( object sender, EventArgs e )
        {
            // project explorer
            projectExplorer.Open();
        }
        private void toolStripButton24_Click( object sender, EventArgs e )
        {
            // object browser
            environment.ShowObjectBrowser();
        }
        private void toolStripButton22_Click( object sender, EventArgs e )
        {
            // task list
            taskList.Open();
        }
        private void toolStripButton23_Click( object sender, EventArgs e )
        {
            // output
            outputWindow.Open();
        }

        // code editor quick strip actions
        private void toolStripButton15_Click( object sender, EventArgs e )
        { // display code completion
            environment.DisplayCodeCompletion();
        }
        private void toolStripButton18_Click( object sender, EventArgs e )
        {
            // comment line(s)
            if ( environment.IsCodeTabOpen() )
                environment.CommentLine();
        }
        private void toolStripButton19_Click( object sender, EventArgs e )
        {
            // uncomment line(s)
            if ( environment.IsCodeTabOpen() )
                environment.UncommentLine();
        }
        private void toolStripButton16_Click( object sender, EventArgs e )
        {
            // unindent
            if ( environment.IsCodeTabOpen() )
                environment.Unindent();
        }
        private void toolStripButton17_Click( object sender, EventArgs e )
        {
            if ( environment.IsCodeTabOpen() )
                environment.Indent();
            // indent
        }

        // beta quick strip actions
        private void toolStripButton25_Click( object sender, EventArgs e )
        {
            // report a bug
            try
            {
                Process.Start( StringTable.BugReportURL );
            }
            catch { }
        }

        // project explorer quick strip actions
        private void toolStripButton3_Click( object sender, EventArgs e )
        {
            // new item
            environment.AddNewItem();
        }
        private void toolStripButton12_Click( object sender, EventArgs e )
        {
            // existing item
            environment.AddExistingItem();
        }

        // tab context menu actions
        private void saveToolStripMenuItem1_Click( object sender, EventArgs e )
        {
            environment.SaveActiveTab();
        }
        private void closeToolStripMenuItem1_Click( object sender, EventArgs e )
        {
            environment.CloseActiveTab();
        }
        private void closeAllButThisToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.CloseAllButActiveTab();
        }

        // editor context menu actions
        private void cutToolStripMenuItem1_Click( object sender, EventArgs e )
        {
            if ( environment.CanCut() )
                environment.Cut();
        }
        private void copyToolStripMenuItem1_Click( object sender, EventArgs e )
        {
            if ( environment.CanCopy() )
                environment.Copy();
        }
        private void pasteToolStripMenuItem1_Click( object sender, EventArgs e )
        {
            if ( environment.CanPaste() )
                environment.Paste();
        }

        // project node context menu actions
        private void newItemToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.AddNewItem();
        }
        private void existingItemToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.AddExistingItem();
        }
        private void folderToolStripMenuItem_Click( object sender, EventArgs e )
        {
            //environment.AddNewFolder();
        }
        private void propertiesToolStripMenuItem_Click( object sender, EventArgs e )
        {
            environment.ShowProjectInfo();
        }
        private void removeToolStripMenuItem1_Click( object sender, EventArgs e )
        {
            environment.CloseProject();
        }
        private void renameToolStripMenuItem1_Click( object sender, EventArgs e )
        {
            environment.RenameProject();
        }

        // code node context menu actions
        private void viewCodeToolStripMenuItem_Click( object sender, EventArgs e )
        {
            TreeNode node = environment.GetSelectedTreeNode();
            if ( node == null )
                return;

            if ( node.Tag is ProjectFile )
            {
                environment.ShowProjectFile( ( ProjectFile )node.Tag );
            }
        }
        private void removeToolStripMenuItem_Click( object sender, EventArgs e )
        {
            TreeNode node = environment.GetSelectedTreeNode();
            if ( node == null )
                return;

            if ( node.Tag is ProjectFile )
            {
                environment.RemoveProjectFile( ( ProjectFile )node.Tag );
            }
        }
        private void renameToolStripMenuItem_Click( object sender, EventArgs e )
        {
            TreeNode node = environment.GetSelectedTreeNode();
            if ( node == null )
                return;

            if ( node.Tag is ProjectFile )
            {
                environment.RenameProjectFile( ( ProjectFile )node.Tag );
            }
        }

        // dock window context menu actions
        private void collapsableToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( collapsableToolStripMenuItem.Checked )
                return;

            floatingToolStripMenuItem.Checked = collapsableToolStripMenuItem.Checked;
            dockableToolStripMenuItem.Checked = collapsableToolStripMenuItem.Checked;
            collapsableToolStripMenuItem.Checked = !collapsableToolStripMenuItem.Checked;

            DockControl dc = ( DockControl )contextMenuStrip5.Tag;
            dc.Collapsed = collapsableToolStripMenuItem.Checked;
        }
        private void dockableToolStripMenuItem_Click( object sender, EventArgs e )
        {
            if ( dockableToolStripMenuItem.Checked )
                return;

            floatingToolStripMenuItem.Checked = dockableToolStripMenuItem.Checked;
            collapsableToolStripMenuItem.Checked = dockableToolStripMenuItem.Checked;
            dockableToolStripMenuItem.Checked = !dockableToolStripMenuItem.Checked;

            DockControl dc = ( DockControl )contextMenuStrip5.Tag;
            if ( dc.Collapsed )
                dc.Collapsed = false;
            dc.OpenDocked();
        }
        private void floatingToolStripMenuItem_Click_1( object sender, EventArgs e )
        {
            if ( floatingToolStripMenuItem.Checked )
                return;

            dockableToolStripMenuItem.Checked = floatingToolStripMenuItem.Checked;
            collapsableToolStripMenuItem.Checked = floatingToolStripMenuItem.Checked;
            floatingToolStripMenuItem.Checked = !floatingToolStripMenuItem.Checked;

            DockControl dc = ( DockControl )contextMenuStrip5.Tag;
            if ( dc.Collapsed )
                dc.Collapsed = false;
            dc.OpenFloating();
        }
        private void closeToolStripMenuItem2_Click( object sender, EventArgs e )
        {
            DockControl dc = ( DockControl )contextMenuStrip5.Tag;
            dc.Close();
        }

        // menus opening
        private void fileToolStripMenuItem_DropDownOpening( object sender, EventArgs e )
        {
            foreach ( ToolStripItem tsi in fileToolStripMenuItem.DropDownItems )
            {
                tsi.Enabled = false;
            }

            newProjectToolStripMenuItem.Enabled = true;
            openProjectToolStripMenuItem.Enabled = true;
            openToolStripMenuItem.Enabled = true;

            if ( environment.IsProjectOpen() )
            {
                closeProjectToolStripMenuItem.Enabled = true;
                saveProjectToolStripMenuItem.Enabled = true;
            }

            if ( environment.IsTabOpen() )
            {
                if ( !environment.IsActiveTabSpecial() )
                {
                    saveToolStripMenuItem.Enabled = true;
                    saveToolStripMenuItem.Text = "&Save '" + environment.GetActiveTabName().TrimEnd( '*' ) + "'";
                }
                else
                {
                    saveToolStripMenuItem.Enabled = false;
                    saveToolStripMenuItem.Text = "&Save";
                }
                closeToolStripMenuItem.Enabled = true;
                closeToolStripMenuItem.Text = "&Close '" + environment.GetActiveTabName().TrimEnd( '*' ) + "'";
            }

            exitToolStripMenuItem.Enabled = true;
        }
        private void editToolStripMenuItem_DropDownOpening( object sender, EventArgs e )
        {
            foreach ( ToolStripItem tsi in editToolStripMenuItem.DropDownItems )
            {
                tsi.Enabled = false;
            }

            if ( environment.CanUndo() )
                undoToolStripMenuItem.Enabled = true;
            if ( environment.CanRedo() )
                redoToolStripMenuItem.Enabled = true;
            if ( environment.CanCut() )
                cutToolStripMenuItem.Enabled = true;
            if ( environment.CanCopy() )
                copyToolStripMenuItem.Enabled = true;
            if ( environment.CanPaste() )
                pasteToolStripMenuItem.Enabled = true;
            if ( environment.CanDelete() )
                deleteToolStripMenuItem.Enabled = true;
            if ( environment.IsTabOpen() )
            {
                findAndReplaceToolStripMenuItem.Enabled = true;
                selectAllToolStripMenuItem.Enabled = true;
            }
        }
        private void projectToolStripMenuItem_DropDownOpening( object sender, EventArgs e )
        {
            foreach ( ToolStripItem tsi in projectToolStripMenuItem.DropDownItems )
            {
                tsi.Enabled = false;
            }

            if ( environment.IsProjectOpen() )
            {
                generateInfoFileToolStripMenuItem.Enabled = true;
                projectPropertiesToolStripMenuItem.Enabled = true;
                addExistingItemToolStripMenuItem.Enabled = true;
                addNewItemToolStripMenuItem.Enabled = true;
            }
        }
        private void toolStripSplitButton1_DropDownOpening( object sender, EventArgs e )
        {
            foreach ( ToolStripItem tsi in toolStripSplitButton1.DropDownItems )
            {
                tsi.Enabled = false;
            }

            if ( environment.IsProjectOpen() )
            {
                addExistingItemToolStripMenuItem1.Enabled = true;
                addNewItemToolStripMenuItem1.Enabled = true;
            }
        }

        // context menu opening
        private void contextMenuStrip1_Opening( object sender, CancelEventArgs e )
        {
            foreach ( ToolStripItem tsi in contextMenuStrip1.Items )
            {
                tsi.Enabled = false;
            }

            string name = environment.GetActiveTabName();

            if ( name != "Object Browser" )
            {
                saveToolStripMenuItem1.Enabled = true;
            }
            closeAllButThisToolStripMenuItem.Enabled = true;
            closeToolStripMenuItem1.Enabled = true;
        }
        private void contextMenuStrip2_Opening( object sender, CancelEventArgs e )
        {
            foreach ( ToolStripItem tsi in contextMenuStrip2.Items )
            {
                tsi.Enabled = false;
            }

            if ( environment.CanCut() )
                cutToolStripMenuItem1.Enabled = true;
            if ( environment.CanCopy() )
                copyToolStripMenuItem1.Enabled = true;
            if ( environment.CanPaste() )
                pasteToolStripMenuItem1.Enabled = true;
        }
        private void sandDockManager1_ShowControlContextMenu( object sender, ShowControlContextMenuEventArgs e )
        {
            if ( environment.IsCodeTab( e.DockControl ) )
            {
                if ( environment.IsTabOpen() )
                {

                    foreach ( TabbedDocument tp in sandDockManager1.Documents )
                    {
                        if ( tp.TabBounds.Contains( e.Position ) )
                        {
                            sandDockManager1.ActiveTabbedDocument = tp;
                            break;
                        }
                    }

                    contextMenuStrip1.Items[0].Text = "Save '" + environment.GetActiveTabName().TrimEnd( '*' ) + "'";
                    contextMenuStrip1.Show( e.DockControl, e.Position );
                }
            }
            else if ( environment.IsSpecialTab( e.DockControl ) )
            {
                if ( ( ( SpecialTab )e.DockControl.Tag ).Type == TabType.ObjectBrowser )
                {
                    contextMenuStrip1.Items[0].Enabled = false;
                    contextMenuStrip1.Items[0].Text = "Save";
                }
                else if ( ( ( SpecialTab )e.DockControl.Tag ).Type == TabType.ProjectInfo )
                    contextMenuStrip1.Items[0].Text = "Save '" + environment.GetActiveTabName() + "'";

                contextMenuStrip1.Show( e.DockControl, e.Position );
            }
            else
            {
                contextMenuStrip5.Tag = e.DockControl;
                contextMenuStrip5.Show( e.DockControl, e.Position );
            }
        }

        private void treeView1_NodeMouseDoubleClick( object sender, TreeNodeMouseClickEventArgs e )
        {
            if ( e.Node == null )
                return;
            if ( e.Node.Tag is ProjectFile )
            {
                environment.ShowProjectFile( ( ProjectFile )e.Node.Tag );
            }
            else if ( e.Node.Tag is SpecialTab )
            {
                // for whatever reason a node opens a special tab
                // might have been planned for double clicking a project node in the treeview
                environment.ShowSpecialTab( ( SpecialTab )e.Node.Tag );
            }
        }
        private void MainForm_FormClosing( object sender, FormClosingEventArgs e )
        {
            e.Cancel = !environment.Exit();
        }

        private void projectExplorer_Closing( object sender, DockControlClosingEventArgs e )
        {
            if ( e.DockControl.Collapsed )
                e.DockControl.Collapsed = false;
        }
        private void taskList_Closing( object sender, DockControlClosingEventArgs e )
        {
            if ( e.DockControl.Collapsed )
                e.DockControl.Collapsed = false;
        }
        private void outputWindow_Closing( object sender, DockControlClosingEventArgs e )
        {
            if ( e.DockControl.Collapsed )
                e.DockControl.Collapsed = false;
        }

        protected override void WndProc( ref Message m )
        {
            switch ( (uint)m.Msg )
            {
                case Util.WM_GLUA_START:
                    fMsg = "";
                    break;
                case Util.WM_GLUA_OPENFILE:
                    fMsg += ( char )m.WParam;
                    break;
                case Util.WM_GLUA_END:
                    environment.OpenFile( fMsg );
                    break;
            }
            base.WndProc( ref m );
        }
    }
}